﻿using JNPF.Basics.Logic;
using JNPF.Basics.Models;
using JNPF.Basics.Models.WorkFlow.Dtos.FlowEngine;
using JNPF.Basics.Models.WorkFlow.Model;
using JNPF.Utils;
using JNPF.Utils.Controller;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace JNPF.Basics.Controller
{
    /// <summary>
    /// 流程引擎
    /// 版 本：V3.0.0
    /// 版 权：引迈信息技术有限公司（https://www.jnpfsoft.com）
    /// 作 者：JNPF开发平台组
    /// 日 期：2018-01-17 
    /// </summary>
    [Route("api/WorkFlow/[controller]")]
    public class FlowEngineController : BaseApiController
    {
        private FlowEngineBll flowEngineBll = new FlowEngineBll();
        private UserBll userBll = new UserBll();
        private FlowTaskBll flowTaskBll = new FlowTaskBll();

        #region GET
        /// <summary>
        /// 列表
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResponseResult> GetList([FromQuery] FlowEngineListQuery input)
        {
            var userList = await userBll.GetList();
            var data = await flowEngineBll.GetList();
            if (!input.enabledMark.IsNullOrEmpty())
            {
                data = data.FindAll(m => m.EnabledMark == input.enabledMark);
            }
            if (!input.keyword.IsNullOrEmpty())
            {
                data = data.FindAll(o => o.FullName.Contains(input.keyword) || o.EnCode.Contains(input.keyword));
            }
            var output = data.Select(x => new FlowEngineListOutput()
            {
                category = x.Category,
                id = x.Id,
                description = x.Description,
                creatorTime = x.CreatorTime,
                creatorUser = userBll.GetUserName(x.CreatorUserId),
                enCode = x.EnCode,
                enabledMark = x.EnabledMark,
                flowTemplateJson = x.FlowTemplateJson,
                formData = x.FormTemplateJson,
                fullName = x.FullName,
                formType = x.FormType,
                icon = x.Icon,
                iconBackground = x.IconBackground,
                lastModifyTime = x.LastModifyTime,
                lastModifyUser = userBll.GetUserName(x.LastModifyUserId),
                sortCode = x.SortCode,
                type = x.Type,
                visibleType = x.VisibleType
            }).ToList();
            return Success(new { list = output });
        }

        /// <summary>
        /// 列表
        /// </summary>
        /// <returns></returns>
        [HttpGet("ListAll")]
        public async Task<ResponseResult> GetListAll()
        {
            var data = await flowEngineBll.GetFlowFormList();
            var output = data.MapToList<FlowEngineListAllOutput>();
            foreach (var item in output)
            {
                item.formData = data.Find(x => x.Id == item.id).FormTemplateJson;
            }
            return Success(new { list = output });
        }

        /// <summary>
        /// 信息
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public async Task<ResponseResult> GetInfo(string id)
        {
            var flowEntity = await flowEngineBll.GetInfo(id);
            var output = flowEntity.MapTo<FlowEngineInfoOutput>();
            output.formData = flowEntity.FormTemplateJson;
            var childNodeModel = output.flowTemplateJson.ToObject<ChildNodeModel>();
            if (childNodeModel.childNode.IsNotEmptyOrNull())
            {
                var type = childNodeModel.childNode.properties.assigneeType;
                if ((int)FlowTaskOperatorEnum.FreeApprover == type)
                {
                    output.freeApprover = 1;
                }
            }
            return Success(output);
        }

        /// <summary>
        /// 获取流程设计列表
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        [HttpGet("Selector")]
        public async Task<ResponseResult> ListSelect(int type)
        {
            var data = (await flowEngineBll.GetList()).FindAll(x => type.Equals(x.FormType) && x.EnabledMark == 1);
            var output = data.MapToList<FlowEngineListSelectOutput>();
            return Success(new { list = output });
        }

        /// <summary>
        /// 表单主表属性
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("{id}/FormDataFields")]
        public async Task<ResponseResult> getFormDataField(string id)
        {
            var entity = await flowEngineBll.GetInfo(id);
            #region 将fields字段值序列化
            var jobj = entity.FormTemplateJson.ToObject();//表单模板信息
            if (jobj != null)
            {
                jobj["fields"] = JsonHelper.ToJson(jobj["fields"]);
            }
            #endregion
            FormDataModel formData = jobj.ToObject<FormDataModel>();
            List<FieldsModel> list = formData.fields.ToList<FieldsModel>();
            List<FormDataField> formDataFieldList = new List<FormDataField>();
            foreach (var item in list)
            {
                if (!"table".Equals(item.__config__.jnpfKey))
                {
                    formDataFieldList.Add(new FormDataField()
                    {
                        vModel = item.__vModel__,
                        label = item.__config__.label
                    });
                }
            }
            return Success(new { list = formDataFieldList });
        }

        /// <summary>
        /// 表单列表
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("{id}/FieldDataSelect")]
        public async Task<ResponseResult> getFormData(string id)
        {
            var flowTaskList = await flowTaskBll.GetTaskList(id);
            var output = flowTaskList.Select(x => new FlowEngineListSelectOutput()
            {
                id = x.Id,
                fullName = x.FullName + "/" + x.EnCode
            }).ToList();
            return Success(new { list = output });
        }

        #endregion

        #region POST
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public async Task<ResponseResult> Delete(string id)
        {
            var flowEngineEntity = await flowEngineBll.GetInfo(id);
            if (flowEngineEntity != null)
            {
                await flowEngineBll.Delete(flowEngineEntity);
            }
            return Success("删除成功");
        }

        /// <summary>
        /// 新建
        /// </summary>
        /// <param name="input">请求参数</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResponseResult> Create([FromBody] FlowEngineCrInput input)
        {
            if (await flowEngineBll.IsExistByEnCode(input.enCode, null))
            {
                return Error("编码已存在");
            }
            if (await flowEngineBll.IsExistByFullName(input.fullName, null))
            {
                return Error("名称已存在");
            }
            var flowEngineEntity = input.MapTo<FlowEngineEntity>();
            flowEngineEntity.FormTemplateJson = input.formData;
            var flowVisibleList = this.GetFlowEngineVisibleList(input.flowTemplateJson);
            await flowEngineBll.Create(flowEngineEntity, flowVisibleList);
            return Success("新建成功");
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="id">主键值</param>
        /// <param name="input">请求参数</param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public async Task<ResponseResult> Update(string id, [FromBody] FlowEngineUpInput input)
        {
            if (await flowEngineBll.IsExistByEnCode(input.enCode, id))
            {
                return Error("编码已存在");
            }
            if (await flowEngineBll.IsExistByFullName(input.fullName, id))
            {
                return Error("名称已存在");
            }
            var flowEngineEntity = input.MapTo<FlowEngineEntity>();
            var flowVisibleList = this.GetFlowEngineVisibleList(input.flowTemplateJson);
            flowEngineEntity.FormTemplateJson = input.formData;
            await flowEngineBll.Update(id, flowEngineEntity, flowVisibleList);
            return Success("更新成功");
        }

        /// <summary>
        /// 更新流程表单状态
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        [HttpPut("{id}/Actions/State")]
        public async Task<ResponseResult> ActionsState(string id)
        {
            var entity = await flowEngineBll.GetInfo(id);
            entity.EnabledMark = entity.EnabledMark == 0 ? 1 : 0;
            await flowEngineBll.Update(id, entity);
            return Success("修改成功");
        }

        /// <summary>
        /// 更新流程表单状态
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        [HttpPost("{id}/Actions/Copy")]
        public async Task<ResponseResult> ActionsCopy(string id)
        {
            var entity = await flowEngineBll.GetInfo(id);
            entity.FullName = entity.FullName + CommonHelper.GetTimeStamp;
            entity.EnCode = entity.EnCode + CommonHelper.GetTimeStamp;
            var flowVisibleList = this.GetFlowEngineVisibleList(entity.FlowTemplateJson);
            await flowEngineBll.Create(entity, flowVisibleList);
            return Success("复制成功");
        }

        /// <summary>
        /// 发布
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        [HttpPost("Release/{id}")]
        public async Task<ResponseResult> Release(string id)
        {
            var entity = await flowEngineBll.GetInfo(id);
            if (entity != null)
            {
                entity.EnabledMark = 1;
                await flowEngineBll.Update(id, entity);
            }
            return Success("发布成功");
        }

        /// <summary>
        /// 停止
        /// </summary>
        /// <param name="id">主键值</param>
        /// <returns></returns>
        [HttpPost("Stop/{id}")]
        public async Task<ResponseResult> Stop(string id)
        {
            var entity = await flowEngineBll.GetInfo(id);
            if (entity != null)
            {
                entity.EnabledMark = 0;
                await flowEngineBll.Update(id, entity);
            }
            return Success("停止成功");
        }
        #endregion

        #region Method
        /// <summary>
        /// 解析流程可见参数
        /// </summary>
        /// <param name="josnStr"></param>
        /// <returns></returns>
        private List<FlowEngineVisibleEntity> GetFlowEngineVisibleList(string josnStr)
        {
            var output = new List<FlowEngineVisibleEntity>();
            var jobj = JsonHelper.ToObject(josnStr)["properties"] as JObject;
            var initiator = jobj["initiator"] as JArray;
            var initiatePos = jobj["initiatePos"] as JArray;
            if (initiator != null && initiator.Count != 0)
            {
                foreach (var item in initiator)
                {
                    var entity = new FlowEngineVisibleEntity();
                    entity.OperatorId = item.ToString();
                    entity.OperatorType = "user";
                    output.Add(entity);
                }
            }
            if (initiatePos != null && initiatePos.Count != 0)
            {
                foreach (var item in initiatePos)
                {
                    var entity = new FlowEngineVisibleEntity();
                    entity.OperatorId = item.ToString();
                    entity.OperatorType = "position";
                    output.Add(entity);
                }
            }
            return output;
        }
        #endregion
    }
}
